﻿static char *ipmsg_id = "@(#)Copyright (C) gaoguangtao 2008-2050   ipmsg.cpp	Ver2.06"; //指向常量的指针，初始化内容为常量
//IPMSG的APP源文件

/* ========================================================================
	Project  Name			: IP Messenger for Win32
	Module Name				: IP Messenger Application Class
	Create					: 2008-02-20(Sat)
    Update					: 2008-02-14(Wed)
	Copyright				: gaoguangtao
	Reference				: 
	======================================================================== */

#include <time.h>
#include "tlib.h"
#include "resource.h"
#include "ipmsg.h"

#define IPMSG_CLASS "ipmsg_class"

TMsgApp::TMsgApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow) : TApp(_hI, _cmdLine, _nCmdShow)
{
	//UINT seed = (UINT)Time();

	//srand(seed); //设置随机数种子
}

TMsgApp::~TMsgApp()
{
}

void TMsgApp::InitWindow(void)
{
	WNDCLASS	wc;
	HWND		hWnd;
	char		class_name[MAX_PATH] = IPMSG_CLASS;
	char        *tok;
	char        *msg;
	char        *p;
	ULONG		nicAddr = 0;

	//将字符串str转换成一个整数并返回结果。
	//参数str 以数字开头，当函数从str 中读到非数字字符则结束转换并将结果返回
	int			port_no = atoi(cmdLine);

	if (port_no == 0)
	{
		port_no = IPMSG_DEFAULT_PORT;
	}

//[[ 处理命令行，现在可以不关注
	if ((tok = strchr(cmdLine, '/')) && separate_token(tok, ' ', &p))
	{
		BOOL	diag = TRUE;
		DWORD	status = 0xffffffff;

		if (_stricmp(tok, "/NIC") == 0)	// NIC
		{
			if (tok = separate_token(NULL, ' ', &p))
			{
				nicAddr = ResolveAddr(tok);
			}
		}
		else if (_stricmp(tok, "/MSG") == 0)
		{
			MsgMng	msgMng(nicAddr, port_no);
			ULONG	command = IPMSG_SENDMSG|IPMSG_NOADDLISTOPT|IPMSG_NOLOGOPT, destAddr;

			while ((tok = separate_token(NULL, ' ', &p)) != NULL && *tok == '/') 
			{
				if (_stricmp(tok, "/LOG") == 0)
				{
					command &= ~IPMSG_NOLOGOPT;
				}
				else if (_stricmp(tok, "/SEAL") == 0)
				{
					command |= IPMSG_SECRETOPT;
				}
			}

			if ((msg = separate_token(NULL, 0, &p)) != NULL)
			{
				diag = FALSE;

				 if ((destAddr = ResolveAddr(tok)) != NULL)
				 {
					 status = msgMng.Send(destAddr, htons(port_no), command, msg) ? 0 : -1;
				 }
			}
		}

		if (nicAddr == 0)
		{
			if (diag)
			{
				MessageBox(0, "ipmsg.exe [portno] [/MSG [/LOG] [/SEAL] <hostname or IP addr> <message>]\r\nipmsg.exe [portno] [/NIC nic_addr]", MSG_STR, MB_OK);
			}

			::ExitProcess(status);
			
			return;
		}
	}
//]] End of 处理命令行，现在可以不关注

	if (port_no != IPMSG_DEFAULT_PORT || nicAddr)
	{
		wsprintf(class_name, nicAddr ? "%s_%d_%s" : "%s_%d", IPMSG_CLASS, port_no, inet_ntoa(*(in_addr *)&nicAddr));
	}

	memset(&wc, 0, sizeof(wc));

	wc.style			= CS_DBLCLKS;
	wc.lpfnWndProc		= TApp::WinProc;
	wc.cbClsExtra 		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= TApp::hI;
	wc.hIcon			= ::LoadIcon(TApp::hI, (LPCSTR)IPMSG_ICON);
	wc.hCursor			= ::LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= NULL;
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= class_name;

	HANDLE	hMutex = ::CreateMutex(NULL, FALSE, class_name);
	::WaitForSingleObject(hMutex, INFINITE);

	//[[ Add by Michael for test
	if (GetLastError() == ERROR_ALREADY_EXISTS) 
	{
		// 如果已有互斥量存在则释放句柄并复位互斥量
		CloseHandle(hMutex);

		//MessageBox(NULL, "程序已经在运行中，不能重复启动！", "提示", MB_OK + MB_ICONWARNING);
      
		hMutex = NULL;

		// 程序退出
		return ;
	}
	//]]

	if ((hWnd = ::FindWindow(class_name, NULL)) != NULL 
		|| ::RegisterClass(&wc) == 0)//如果RegisterClass函数失败，返回值为0
	{
		if (hWnd != NULL)
		{
			::SetForegroundWindow(hWnd); //该函数将创建指定窗口的线程设置到前台，并且激活该窗口。
		}
		
		::ExitProcess(0xffffffff);
		
		return;
	}

	//在这个之前已经注册了两个窗体TAPP 和 ipmsg_class, 其消息处理函数都是TApp::WinProc
	this->mainWnd = new TMainWin(nicAddr, port_no, NULL);
	this->mainWnd->Create(class_name, // 见line：121
		                  IP_MSG, 
						  WS_OVERLAPPEDWINDOW | (IsNewShell() ? WS_MINIMIZE : 0),
						  0,
						  NULL); //virtual
	
	::ReleaseMutex(hMutex);
	::CloseHandle(hMutex);
}


//////////////////////////////////////////////////////////////////////////
//                       飞鸽传输 启动函数
//////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
				   int nCmdShow)
{
	//TODO:检测是否有飞鸽运行，如果有提示用户，并推出程序

	TMsgApp	app(hInstance, lpCmdLine, nCmdShow); //这种初始化方式，其内存是存放在栈上，而new初始化的内存是分配在堆上

	return app.Run(); //Run 里边有消息循环处理
}